/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package pl.edu.amu.wmi.kino.visualjavafx.visualjavafxgui.editor.visual;

import java.util.Iterator;
import java.util.Set;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JPanel;
import org.netbeans.api.visual.model.ObjectSceneEvent;
import org.netbeans.api.visual.model.ObjectSceneEventType;
import org.netbeans.api.visual.model.ObjectSceneListener;
import org.netbeans.api.visual.model.ObjectState;
import org.netbeans.core.spi.multiview.CloseOperationState;
import org.netbeans.core.spi.multiview.MultiViewElement;
import org.netbeans.core.spi.multiview.MultiViewElementCallback;
import org.netbeans.spi.palette.PaletteController;
import org.openide.awt.UndoRedo;
import org.openide.nodes.Node;
import org.openide.text.DataEditorSupport;
import org.openide.util.Lookup;
import org.openide.util.lookup.AbstractLookup;
import org.openide.util.lookup.InstanceContent;
import org.openide.windows.TopComponent;
import pl.edu.amu.wmi.kino.visualjavafx.model.api.ModelChangeListener;
import pl.edu.amu.wmi.kino.visualjavafx.model.api.ModelChangeNotifier;
import pl.edu.amu.wmi.kino.visualjavafx.model.api.VisualJavaFxModelProvider;
import pl.edu.amu.wmi.kino.visualjavafx.model.objects.Application;
import pl.edu.amu.wmi.kino.visualjavafx.nodes.factory.NodeFactory;
import pl.edu.amu.wmi.kino.visualjavafx.visualjavafxgui.editor.visual.VisualScene.SceneNotifier;
import pl.edu.amu.wmi.kino.visualjavafx.visualjavafxgui.editor.visual.VisualScene.WidgetCreator;
import pl.edu.amu.wmi.kino.visualjavafx.visualjavafxgui.editor.visual.palette.PaletteCreator;
/**
 *
 * @author psychollek
 */
public class VisualJavaFxVisualEditor implements MultiViewElement{

    private JComponent toolbar = null;
    private MultiViewElementCallback callback = null;
    private DataEditorSupport es = null;

    private final VisualScene scene = new VisualScene();
    private final ScenePanel scenePanel = new ScenePanel(scene);
    private final InstanceContent ic = new InstanceContent();
    private final Lookup lookup = new AbstractLookup(ic);

    public VisualJavaFxVisualEditor(DataEditorSupport es) {
        this.es = es;
        prepareScene(getProvider(es));
        preparePalette();
        prepareScenePanel();
    }

    private VisualJavaFxModelProvider getProvider(DataEditorSupport des){
        return des.getDataObject().getLookup().lookup(VisualJavaFxModelProvider.class);
    }

    private void prepareScene(VisualJavaFxModelProvider provider){
        //setting model
        WidgetCreator wc = scene.getLookup().lookup(WidgetCreator.class);
        Application app = provider.getModel();
        wc.setModel(app.getFrames().get(0));
        //setting bi-directional notification with model
        SceneNotifier sn = scene.getLookup().lookup(SceneNotifier.class);
        sn.addModelChangeListener(provider);
        provider.addModelChangeListener(sn);
        //setting selection listener
        scene.addObjectSceneListener(new ObjectSceneSelectionListener(), ObjectSceneEventType.OBJECT_SELECTION_CHANGED);
    }

    private void preparePalette(){
        PaletteController palette = PaletteCreator.createPallete();
        ic.add(palette);
    }

    private void prepareScenePanel(){
        scenePanel.setDropTarget(new VisualJavaFxDropHandler(scenePanel, scene));
    }

    @Override
    public JComponent getVisualRepresentation() {
        return scenePanel;
    }

    @Override
    public JComponent getToolbarRepresentation() {
        if (toolbar == null){
            toolbar = new JPanel();
        }
        return toolbar;
    }

    @Override
    public Action[] getActions() {

        Action[] retValue;

        if (callback != null) {
            retValue = callback.createDefaultActions();
        } else {
            retValue = new Action[0];
        }
        return retValue;

    }

    @Override
    public Lookup getLookup() {
        return lookup;
    }

    @Override
    public void componentOpened() {
        if (es instanceof ModelChangeListener){
            VisualJavaFxModelProvider provider = es.getDataObject().getLookup().lookup(VisualJavaFxModelProvider.class);
            provider.addModelChangeListener((ModelChangeListener) es);
        }
        
    }

    @Override
    public void componentClosed() {
    }

    @Override
    public void componentShowing() {
        if (callback != null){
            String title;
            title = es.getDataObject().getName();
            if (es.isModified()){
                title = title + "*";
            }
            callback.updateTitle(title);
        }
    }

    @Override
    public void componentHidden() {
    }

    @Override
    public void componentActivated() {
    }

    @Override
    public void componentDeactivated() {
    }

    @Override
    public UndoRedo getUndoRedo() {
        return null;
    }

    @Override
    public void setMultiViewCallback(MultiViewElementCallback val) {
        this.callback = val;
    }

    @Override
    public CloseOperationState canCloseElement() {
        return CloseOperationState.STATE_OK;
    }

    private class ObjectSceneSelectionListener implements ObjectSceneListener{

        @Override
        public void selectionChanged(ObjectSceneEvent event, Set<Object> previousSelection, Set<Object> newSelection) {

            Node n = null;
            for (Iterator<Object> it = newSelection.iterator(); it.hasNext();) {
                Object object = it.next();
                n = NodeFactory.generateFrom(object);
                if (n != null){
                    while(it.hasNext()){
                        it.next();
                    }
                }
            }
            if (n.getLookup().lookup(ModelChangeNotifier.class) != null){
                n.getLookup().lookup(ModelChangeNotifier.class).addModelChangeListener(getProvider(es));
            }
            setActivatedNode(n);
        }

        private void setActivatedNodes(Node[] nodes){
            if (callback != null){
                TopComponent par = callback.getTopComponent();
                par.setActivatedNodes(nodes);
            }
        }
        private void setActivatedNode(Node n){
            Node[] nodes = {n};
            setActivatedNodes(nodes);
        }

        @Override
        public void highlightingChanged(ObjectSceneEvent event, Set<Object> previousHighlighting, Set<Object> newHighlighting) {}
        @Override
        public void hoverChanged(ObjectSceneEvent event, Object previousHoveredObject, Object newHoveredObject) {}
        @Override
        public void focusChanged(ObjectSceneEvent event, Object previousFocusedObject, Object newFocusedObject) {}
        @Override
        public void objectAdded(ObjectSceneEvent event, Object addedObject) {}
        @Override
        public void objectRemoved(ObjectSceneEvent event, Object removedObject) {}
        @Override
        public void objectStateChanged(ObjectSceneEvent event, Object changedObject, ObjectState previousState, ObjectState newState) {}


    }
}
